home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / DiskUtil / Info / FreeSpace.lha / FreeSpace.c < prev    next >
C/C++ Source or Header  |  1993-08-28  |  12KB  |  326 lines

  1. /*
  2.  
  3.     FreeSpace - graphically displays free space for each mounted volume
  4.     Copyright 1993 Barry McConnell
  5.     bmccnnll@unix1.tcd.ie
  6.  
  7. */
  8.  
  9.  
  10. #include <exec/execbase.h>
  11. #include <exec/memory.h>
  12. #include <dos/dos.h>
  13. #include <graphics/gfxbase.h>
  14. #include <intuition/intuition.h>
  15. #include <intuition/screens.h>
  16. #include <graphics/text.h> 
  17. #include <libraries/gadtools.h>
  18. #include <workbench/startup.h>
  19. #include <workbench/workbench.h>
  20.  
  21. #include <proto/dos.h>
  22. #include <proto/exec.h>
  23. #include <proto/intuition.h>
  24. #include <proto/graphics.h>
  25. #include <proto/gadtools.h>
  26. #include <proto/icon.h>
  27.  
  28. #include <stdio.h>
  29. #include <string.h>
  30.  
  31. #define TEXTLENGTH 36  /* max length of volume statistics */
  32.  
  33. struct volume  /* to store volume data */
  34.     {
  35.     struct volume *next;
  36.     struct volume *prev;
  37.     char *name;  /* name of volume */
  38.     char *text;  /* statistics in ASCII */
  39.     LONG free, used, percentage;
  40.     };
  41.  
  42. static UBYTE *version = "$VER: FreeSpace 1.0 (27.08.93)";
  43. extern struct ExecBase *SysBase;
  44. UWORD osver = 0;  /* Kickstart version */
  45.  
  46. UWORD __chip waitPointer[] =
  47.     {
  48.     0x0000, 0x0000,
  49.     0x0400, 0x07c0,
  50.     0x0000, 0x07c0,
  51.     0x0100, 0x0380,
  52.     0x0000, 0x07e0,
  53.     0x07c0, 0x1ff8,
  54.     0x1ff0, 0x3fec,
  55.     0x3ff8, 0x7fde,
  56.     0x3ff8, 0x7fbe,
  57.     0x7ffc, 0xff7f,
  58.     0x7efc, 0xffff,
  59.     0x7ffc, 0xffff,
  60.     0x3ff8, 0x7ffe,
  61.     0x3ff8, 0x7ffe,
  62.     0x1ff0, 0x3ffc,
  63.     0x07c0, 0x1ff8,
  64.     0x0000, 0x07e0,
  65.     0x0000, 0x0000,
  66.     };
  67.  
  68.  
  69. /*
  70.     Display a busy pointer in the current window, and prevent user from
  71.     clicking on any gadgets.
  72. */
  73.  
  74. void busyPointer(struct Window *myWindow, struct Requester *myReq)
  75. {
  76. InitRequester(myReq);
  77. Request(myReq, myWindow);
  78. if (osver < 39)
  79.     SetPointer(myWindow, waitPointer, 16, 16, -6, 0);
  80. else
  81.     SetWindowPointer(myWindow,  WA_BusyPointer,     TRUE,
  82.                                 WA_PointerDelay,    TRUE,
  83.                                 TAG_END);
  84. }
  85.  
  86.  
  87. /*
  88.     Restore the pointer to normal.
  89. */
  90.  
  91. void normalPointer(struct Window *myWindow, struct Requester *myReq)
  92. {
  93. ClearPointer(myWindow);
  94. EndRequest(myReq, myWindow);
  95. }
  96.  
  97.  
  98. /*
  99.     Compare two strings. Like "strcmp" but case-insensitive.
  100. */
  101.  
  102. int Compare(char *s, char *t)
  103. {
  104. for (; ((*s & ~32) == (*t & ~32)) && *s; s++, t++)  /* sorry, K&R ;-) */
  105.     ;
  106. return (*s & ~32) - (*t & ~32);
  107. }
  108.  
  109.  
  110. /*
  111.     Alphabetically insert "node" into "list".
  112. */
  113.  
  114. void Sort(struct List *list, struct volume *node)
  115. {
  116. struct volume *temp = (struct volume *)list -> lh_Head;
  117.  
  118. while (temp -> next && Compare(temp -> name, node -> name) < 0)
  119.     temp = temp -> next;
  120.  
  121. Insert(list, (struct Node *)node, (struct Node *)temp -> prev);
  122. }
  123.  
  124.  
  125. void main(int argc, char *argv[])
  126. {
  127. struct DiskObject   *myIcon;
  128. struct Screen       *myScreen;
  129. struct Window       *myWindow;
  130. struct Requester    tinyReq;
  131. struct VisualInfo   *visInfo;
  132. struct TextFont     *propFont;
  133. struct TextExtent   fontSize;
  134. struct RastPort     myRast, *winRast;
  135. struct DosList      *dl;
  136. struct InfoData     info;
  137. struct Remember     *memoryKey;
  138. struct List         volumeList;
  139. struct IntuiMessage *message;
  140. struct volume       *volume;
  141. int                 maxNameLen = 0, maxTextLen = 0, count = 0, memOkay = TRUE, tempLen,
  142.                     winLeft = 0, winTop = 0, winWidth, winHeight, pen = 3, title, gap, rectSize;
  143. ULONG               class, code;
  144. UWORD               height;
  145. BYTE                i,j;
  146. BPTR                lock;
  147. char                **tools, *string, *myName, *name, *dest, freeSuffix, usedSuffix;
  148.  
  149. struct EasyStruct about =
  150.     {
  151.     sizeof(struct EasyStruct),
  152.     0,
  153.     "About FreeSpace",
  154.     "FreeSpace v1.0 -- Freely Distributable\nCopyright 1993 Barry McConnell\nbmccnnll@unix1.tcd.ie\n\nDedicated to Niall Murphy :-)",
  155.     "Okay"
  156.     };
  157.  
  158. IntuitionBase = NULL;
  159. DOSBase = NULL;
  160. GfxBase = NULL;
  161. GadToolsBase = NULL;
  162. osver = SysBase -> LibNode.lib_Version;  /* running under 2.0, 3.0, ...? */
  163.  
  164. if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37))
  165. if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))
  166. if (GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))
  167. if (GadToolsBase = OpenLibrary("gadtools.library", 37))
  168. if (IconBase = OpenLibrary("icon.library", 37))
  169.     {
  170.     if (!argc)  /* only look at ToolTypes if started from Workbench */
  171.         {
  172.         myName = ((struct WBStartup *)argv) -> sm_ArgList -> wa_Name;  /* find ourselves */
  173.         if (myIcon = GetDiskObject(myName));  /* read in .info file */
  174.             {
  175.             tools = myIcon -> do_ToolTypes;
  176.             if (string = FindToolType(tools, "LEFT"))
  177.                 sscanf(string, "%d", &winLeft);
  178.             if (string = FindToolType(tools, "TOP"))
  179.                 sscanf(string, "%d", &winTop);
  180.             if (string = FindToolType(tools, "PEN"))
  181.                 sscanf(string, "%d", &pen);
  182.             FreeDiskObject(myIcon);
  183.             }
  184.         }
  185.  
  186.     myScreen = LockPubScreen(NULL);  /* get a lock on the Workbench screen */
  187.     visInfo = GetVisualInfo(myScreen, TAG_END);  /* GadTools needs this */
  188.     propFont = OpenFont(myScreen -> Font);
  189.     FontExtent(propFont, &fontSize);  /* figure out pixel size of fonts */
  190.     height = fontSize.te_Height;
  191.  
  192.     InitRastPort(&myRast);  /* dummy RastPort for getting string lengths */
  193.     SetFont(&myRast, propFont);
  194.  
  195.     memoryKey = NULL;
  196.     volumeList.lh_Head      = (struct Node *)&volumeList.lh_Tail;
  197.     volumeList.lh_Tail      = NULL;
  198.     volumeList.lh_TailPred  = (struct Node *)&volumeList.lh_Head;
  199.  
  200.     dl = LockDosList(LDF_VOLUMES | LDF_READ);
  201.     while ((dl = NextDosEntry(dl, LDF_VOLUMES)) && memOkay)  /* walk through list of volumes */
  202.         {
  203.         if ((volume = AllocRemember(&memoryKey, sizeof(struct volume), MEMF_ANY))
  204.             && (volume -> text = AllocRemember(&memoryKey, TEXTLENGTH, MEMF_ANY)))
  205.             {
  206.             name = (char *)BADDR(dl -> dol_Name);  /* BCPL string */
  207.             i = *((BYTE *)name);  /* length */
  208.             dest = volume -> name = AllocRemember(&memoryKey, i+2, MEMF_ANY);
  209.             for (j = 1; i; i--)
  210.                 *(dest++) = name[j++];
  211.             *(dest++) = ':';
  212.             *(dest) = 0;
  213.  
  214.             lock = Lock(volume -> name, ACCESS_READ);  /* get a lock on this volume */
  215.             *(--dest) = 0;  /* remove trailing colon */
  216.  
  217.             Info(lock, &info);
  218.             freeSuffix = usedSuffix = 'K';  /* default */
  219.             volume -> free = (info.id_NumBlocks - info.id_NumBlocksUsed) * info.id_BytesPerBlock / 1024;
  220.             volume -> used = info.id_NumBlocksUsed * info.id_BytesPerBlock / 1024;
  221.             volume -> percentage = info.id_NumBlocksUsed * 100 / info.id_NumBlocks;
  222.             if (volume -> free > 9999)
  223.                 {
  224.                 volume -> free = volume -> free / 1024;  /* move up to MB */
  225.                 freeSuffix = 'M';
  226.                 }
  227.             if (volume -> used > 9999)
  228.                 {
  229.                 volume -> used = volume -> used / 1024;
  230.                 usedSuffix = 'M';
  231.                 }
  232.             sprintf(volume -> text, "%d%% full, %d%c free, %d%c in use", volume -> percentage, volume -> free, freeSuffix, volume -> used, usedSuffix);
  233.  
  234.             SetSoftStyle(&myRast, FSF_BOLD, FSF_BOLD);
  235.             tempLen = TextLength(&myRast, volume -> name, j-1);
  236.             if (maxNameLen < tempLen)
  237.                 maxNameLen = tempLen;
  238.             SetSoftStyle(&myRast, NULL, FSF_BOLD);  /* turn off bold */
  239.             tempLen = TextLength(&myRast, volume -> text, strlen(volume -> text));
  240.             if (maxTextLen < tempLen)
  241.                 maxTextLen = tempLen;
  242.  
  243.             Sort(&volumeList, volume);
  244.             UnLock(lock);
  245.             count++;
  246.             }
  247.         else
  248.             memOkay = FALSE;
  249.         }
  250.     UnLockDosList(LDF_VOLUMES | LDF_READ);
  251.  
  252.     if (memOkay)
  253.         {
  254.         title = (myScreen -> WBorTop) + height + 1 + INTERHEIGHT;
  255.         gap = title + propFont -> tf_Baseline;
  256.         winWidth = INTERWIDTH*2 + maxTextLen;
  257.         winHeight = title + count * (height*2 + INTERHEIGHT*3) - INTERHEIGHT + 2;  /* allow a couple of pixels for the comma */
  258.  
  259.         if (myWindow = OpenWindowTags(NULL, WA_Title,       "FreeSpace",
  260.                                             WA_Left,        winLeft,
  261.                                             WA_Top,         winTop,
  262.                                             WA_Width,       winWidth,
  263.                                             WA_Height,      winHeight,
  264.                                             WA_DragBar,     TRUE,
  265.                                             WA_DepthGadget, TRUE,
  266.                                             WA_CloseGadget, TRUE,
  267.                                             WA_Activate,    TRUE,
  268.                                             WA_RMBTrap,     TRUE,
  269.                                             WA_IDCMP,       IDCMP_CLOSEWINDOW | RAWKEY,
  270.                                             WA_PubScreen,   myScreen,
  271.                                             TAG_END))
  272.             {
  273.             volume = (struct volume *)volumeList.lh_Head;
  274.             winRast = myWindow -> RPort;
  275.             SetFont(winRast, propFont);  /* defaults to GfxBase -> DefaultFont, which is not what we want */
  276.  
  277.             for (i = 0; i < count; volume = volume -> next, i++)
  278.                 {
  279.                 SetAPen(winRast, 1);  /* black */
  280.                 Move(winRast, INTERWIDTH, gap + i * (height*2 + INTERHEIGHT*3));
  281.                 SetSoftStyle(winRast, FSF_BOLD, FSF_BOLD);
  282.                 Text(winRast, volume -> name, strlen(volume -> name));
  283.                 Move(winRast, INTERWIDTH, gap + height + INTERHEIGHT + i * (height*2 + INTERHEIGHT*3));
  284.                 SetSoftStyle(winRast, NULL, FSF_BOLD);
  285.                 Text(winRast, volume -> text, strlen(volume -> text));
  286.                 DrawBevelBox(winRast, (INTERWIDTH*3) / 2 + maxNameLen, title + i * (height*2 + INTERHEIGHT*3),
  287.                                 winWidth - maxNameLen - (INTERWIDTH*5) / 2, height,
  288.                                 GTBB_Recessed,  TRUE,
  289.                                 GT_VisualInfo,  visInfo,
  290.                                 TAG_END);
  291.                 SetAPen(winRast, pen);  /* pen to fill with (user's choice) */
  292.                 rectSize = winWidth - maxNameLen - INTERWIDTH*3;
  293.                 rectSize = (rectSize * volume -> percentage) / 100;
  294.                 RectFill(winRast, (INTERWIDTH*3) / 2 + maxNameLen + 2, title + i * (height*2 + INTERHEIGHT*3) + 1,
  295.                             (INTERWIDTH*3) / 2 + maxNameLen + 1 + rectSize, title + i * (height*2 + INTERHEIGHT*3) + height - 2);
  296.                 }
  297.  
  298.             do
  299.                 {
  300.                 WaitPort(myWindow -> UserPort);
  301.                 if (message = (struct IntuiMessage *)GetMsg(myWindow -> UserPort))
  302.                     class = message -> Class, code = message -> Code;
  303.                 ReplyMsg((struct Message *)message);
  304.                 if (class == RAWKEY && code == 95)  /* Help key */
  305.                     {
  306.                     busyPointer(myWindow, &tinyReq);
  307.                     EasyRequest(NULL, &about, NULL, NULL);
  308.                     normalPointer(myWindow, &tinyReq);
  309.                     }
  310.                 }
  311.             while (!(class == IDCMP_CLOSEWINDOW));
  312.  
  313.             CloseWindow(myWindow);
  314.             }
  315.         }
  316.     FreeRemember(&memoryKey, TRUE);
  317.     CloseFont(propFont);
  318.     FreeVisualInfo(visInfo);
  319.     UnlockPubScreen(NULL, myScreen);
  320.     }
  321. CloseLibrary(GadToolsBase);  /* safe to pass NULL */
  322. CloseLibrary((struct Library *)GfxBase);
  323. CloseLibrary((struct Library *)DOSBase);
  324. CloseLibrary((struct Library *)IntuitionBase);
  325. }
  326.